#ifndef OBJECT_POOL_H
#define OBJECT_POOL_H

#include <iostream>

constexpr static size_t POOL_SIZE = 128 * 1024;

template <typename T>
class ObjectPool
{

public:
    ObjectPool()
    {
        _objSize = sizeof(T) >= sizeof(void *) ? sizeof(T) : sizeof(void *);
    }
/* 
    ~ObjectPool()
    {
        // if(_remainSize > 0){
        //     free(_pool);
        // } 

        void *next = *(void **)_freeList;
        while(_freeList){
            free(_freeList);
            _freeList = next;
            next = *(void **)next;
        }
    }
 */
    T *alloc()
    {
        T *obj;

        if (_freeList)
        {
            obj = (T *)_freeList;
            _freeList = *(void **)obj;
        }
        // 如果当前定长内存池剩余不足以构建一个对象时
        else
        {
            if (_objSize > _remainSize)
            {
                _pool = (char *)malloc(POOL_SIZE);
                if (!_pool)
                {
                    throw std::bad_alloc();
                }

                _remainSize = POOL_SIZE;
            }
            obj = (T *)_pool;
            _pool += _objSize;
            _remainSize -= _objSize;
        }

        new (obj) T;
        return obj;
    }

    void dealloc(T *obj)
    {
        obj->~T();

        *(void **)obj = _freeList;
        _freeList = obj;
    }

private:
    char *_pool = nullptr;
    size_t _remainSize = 0;
    size_t _objSize;
    void *_freeList = nullptr;
};

#endif